#!/bin/bash
# mkapp.sh is a script for builting apps for joolix
# Author: xiooli <http://joolix.com>
# Licence: GPLv2
# 2009.08.15

if [ -e "`dirname $0`/mkapp.conf" ]; then
	. "`dirname $0`/mkapp.conf"
else
	echo "未找到配置文件：（"
	exit
fi

MK_FACKROOT() {
	
	Fackrootok=""
	#将选择的 app 模块挂载到挂载点并将需要的东西都挂载到联合文件系统上。

	local choise yn yn1 i j mntpoint aufsmnt dir

	echo "在 apps 目录下找到如下的 app 模块，请选择要使用的模块(选择数字序号)："
	ls "$Apps"/*app|grep -n .
	read -p "请选择，多项间以空格分隔：" choise
	for i in $choise; do 
		apps[${j:-0}]="$(ls "$Apps"/*app|grep -n .|grep "$i:"|sed 's/^[0-9]*://')"
		((j++))
	done
	echo ${apps[@]}
	j=""
	[ ! "${apps[0]}" ] && echo "未选择模块！" && exit
	echo -ne "将挂载选中的 app 模块：\n${apps[@]} \n是否继续？ [y/n] : "
	read yn
	[ "$yn" = "y" ] && {
		#先在 mnt 里面创建挂载点并挂载之
		read -p "将清空 $MNT, $Changes 和 $Kernel 里面的内容，是否继续？ [y/n]" yn1
		[ "$yn1" = "y" ] && rm -rf "$MNT"/* && rm -rf "$Changes"/* \
		&& rm -rf "$Kernel"/*
		
		[ "$yn1" = "n" ] && echo "略过清空 $MNT, $Kernel 和 $Changes"
		for j in ${apps[@]}; do
			mntpoint="$MNT/`basename $j|sed 's/\.app//'`"
			[ ! -d "$mntpoint" ] && mkdir "$mntpoint"
			mount -o loop -t squashfs "$j" "$mntpoint"
			[ $? -ne 0 ] && echo "挂载 squashfs 失败！" && exit
			aufsmnt=":${mntpoint}${aufsmnt}"
		done
		mount -t aufs -o br:"$Changes""$aufsmnt" aufs "$Fackroot"
		[ $? -ne 0 ] && echo "挂载 aufs 失败！" && exit
		
		for dir in boot usr/src; do #lib/modules lib/firmware; do
			[ ! -d "$Kernel/$dir" ] && mkdir -p "$Kernel/$dir"
			[ ! -d "$Fackroot/$dir" ] && mkdir -p "$Fackroot/$dir"
			mount --bind "$Kernel/$dir" "$Fackroot/$dir"
			[ $? -ne 0 ] && echo "绑定 $dir 目录失败！" && exit
		done
	
		cd "$Fackroot"
	
		for dir in proc sys dev; do
			[ ! -d ./$dir ] && mkdir ./$dir
			mount --bind /$dir ./$dir
		done

		mount --bind "$Pkgcache" ./var/cache/pacman/pkg/
		[ $? -ne 0 ] && echo "绑定 pkgcache 目录失败！" && exit
		mount --bind "$Synccache" ./var/lib/pacman/sync/
		[ $? -ne 0 ] && echo "绑定 synccache 目录失败！" && exit
		cd -		
	} && echo "fackroot 目录搭建完毕，可以运行 chroot 了！" && Fackrootok="yes"
}

MK_SQF() {
	
	echo "压制 squashfs ... "
	rm -f "$2"
	mksquashfs "$1" "$2" -b 256K $3 $4 $5 $6 $7 $8 $9
	[ $? -ne 0 ] && echo "压制 app 模块失败！" && exit
	chmod a-wx "$2"
	chmod a+r "$2"
}

UMOUNT_ALL() {
	
	echo "卸载所有已挂载的目录..."
	for i in "$Fackroot/var/cache/pacman/pkg/" \
		"$Fackroot/var/lib/pacman/sync/" \
		"$Fackroot/boot" "$Fackroot/usr/src" \
		"$Fackroot/lib/modules" "$Fackroot/lib/firmware" \
		"$Fackroot/proc" "$Fackroot/sys" "$Fackroot/dev" \
		"$Fackroot" "$MNT"/*; do
		[ -d "$i" ] && {
			echo "卸载 $i "
			umount "$i"
		}
	done
	Fackrootok=""
}

BUILT_INITRD() {
	
	local appname appversion appbuilddate appsize appinfodir item

	echo "至少需要 001-core.app"
	UMOUNT_ALL
	MK_FACKROOT
	[ "$Fackrootok" != "yes" ] && echo "Fackroot 没有搭建好，退出！" && exit
	cp -af "$Forkernel"/* "$Fackroot"
	[ $? -eq 0 ] && read -p "预处理完成，是否安装内核并创建 initrd？ [y/n] " yn
	[ "$yn" = "y" ] && {
		yn=""
		read -p "是否更新数据库并安装内核, 不更新数据库并安装内核或者进入交互模式 [y/n/i] " yn
		if [ "$yn" = "y" ]; then
			chroot "$Fackroot" pacman -Syf kernel26 kernel26-firmware
		elif [ "$yn" = "n"  ]; then
			chroot "$Fackroot" pacman -Sf kernel26 kernel26-firmware
		else
			chroot "$Fackroot"
		fi
		[ $? -eq 0 ] && echo "清理不要的东西 ..." \
		&& {
			UMOUNT_ALL
			[ "$Fackroot" ] && \
			read -p "将清理 "$Kernel"/etc, "$Kernel"/boot 和 $Kernel/usr/src [y/n] " yn
			[ "$yn" = "y" ] && yn="" && {

				echo "复制 "$Kernel"/boot/ 里面的东西到 "$Initrd""
				cp -a "$Kernel"/boot/initrd.gz "$Initrd/initrd.gz" 2>/dev/null
				[ $? -ne 0 ] && cp -a "$Kernel"/boot/kernel26.img "$Initrd/initrd.gz"
				cp -a "$Kernel"/boot/vmlinuz26 "$Initrd/vmlinuz"
				rm -rf "$Kernel"/etc "$Kernel"/boot/* "$Kernel"/usr

				# 清除 aufs 添加的标记
				find "$Kernel" -iname "\.wh\.\.wh\.\.opq" -exec rm {} \;
				find "$Kernel" -iname "\.keep*" -exec rm {} \;
				echo
			} && read -p "是否压制 002-kernel.app ? [y/n] " yn && \
			{
				[ "$yn" = "y" ] && {
					
					# 添加包信息
					[ ! -d "$Kernel/var/lib/joopac/local" ] && mkdir -p "$Kernel/var/lib/joopac/local"
					appname="kernel"
					appversion="`date +%y.%m.%d`"
					appbuilddate="`date +%s`"
					appsize="`du -sb $Kernel|awk '{print $1}'`"
					appinfodir="$Kernel/var/lib/joopac/local/${appname}-${appversion}"
					mkdir "$appinfodir"
					ls "$Changes/var/lib/pacman/local" > "$appinfodir"/pkgs
					cp "$Kernelinfo" "$appinfodir/desc"
					for item in appname appversion appbuilddate appsize Applicence \
						Apparch Packager; do
						eval "sed -i \"s/$item/\$$item/\" \"$appinfodir/desc\""
					done

					[ ! -d "$Kernel/var/lib/pacman/local/" ] && \
					mkdir -p "$Kernel/var/lib/pacman/local/"
					echo "复制 $Changes/var/lib/pacman/local/kernel* 到 $Kernel/var/lib/pacman/local/"
					cp -a "$Changes"/var/lib/pacman/local/kernel* \
					"$Kernel/var/lib/pacman/local/"

					if [ -f "$Out/002-kernel.app" ];then
						read -p "已经存在 002-kernel.app, 请另外取一个名字：" nm
						[ "$nm" ] && MK_SQF "$Kernel" "$Out/${nm/.app}.app"
					else
						MK_SQF "$Kernel" "$Out/002-kernel.app"
					fi

				} && echo "作业成功完成，你可以在 "$Initrd" 和 $Out 找到它们。"
				yn=""
		   	}
		}
	}
}

MK_APP() {

	local appname appversion appbuilddate appsize appinfodir item editor

	# 先卸载掉以前因异常退出等原因可能没有卸载掉的目录
	UMOUNT_ALL
	MK_FACKROOT
	[ "$Fackrootok" != "yes" ] && echo "Fackroot 没有搭建好，退出！" && exit
	echo -e "chroot 到 $Fackroot ...\n 成功后你可以在里面进行软件安装/配置\n \
	完成后按 ctrl+D 退出，然后按提示进行下一步操作。"
	chroot "$Fackroot"
	UMOUNT_ALL

	cd "$Fackroot"
	rm -rf "$Changes/var/log/pacman.log"

	# 压制 app 模块
	read -p "是否将 $Changes 里面的东西压制成 app 模块吗？ [y/n]" yn
	[ "$yn" = "y" ] && {

		rm -rf "$Changes"/.[a-z]*
		[ ! -d "$Appinfodir" ] && mkdir -p "$Appinfodir"
		
		read -p "请输入模块的名字( .app 后缀可以省略)：" nm
		[ "$nm" ] && {
			appname=${nm%.app};appname="${appname#[0-9]*-}"
			appversion="`date +%y.%m.%d`"
			appbuilddate="`date +%s`"
			appsize="`du -sb $Changes|awk '{print $1}'`"
			appinfodir="${Appinfodir}/${appname}-${appversion}"
			mkdir "$appinfodir"
			ls "$Changes/var/lib/pacman/local" > "$appinfodir"/pkgs
			cp "$Appinfo" "$appinfodir"
			for item in appname appversion appbuilddate appsize Applicence \
				Apparch Packager; do
				eval "sed -i \"s/$item/\$$item/\" \"$appinfodir/`basename $Appinfo`\""
			done
			read -p "需要编辑 app 模块的信息文件，请选择你最熟悉的编辑器：" editor
			editor="`which $editor`"; editor="${editor:-nano}"
			eval $editor "$appinfodir/`basename $Appinfo`"
			read -p "按任意键继续" anykey

			# 递归删除空目录
			i=0
			while [ "${i}" -le 5 ]; do
				find "$Changes" -type d -exec rmdir {} 2>/dev/null \;
				((i++))
			done
			
			# 清除 aufs 添加的标记
			find "$Changes" -iname "\.wh\.\.*" -exec rm -rf {} \; 
			find "$Changes" -iname "\.keep*" -exec rm -rf {} \;

			MK_SQF "$Changes" "$Out/${nm/.app}.app" \
			&& echo "模块已经成功压制，你可以在 $Out/${nm/.app}.app 找到它。"
		}
	}
}

#==================MAIN====================

case $1 in
	-h)
	echo -e "$0 -i : 创建 initrd 文件和内核包 002-kernel.app\n$0 -a : 创建软件模块（交互模式）"
	;;
	-i)
	[ "$UID" -ne 0 ] && echo "运行此项功能需要 root 权限！"
	BUILT_INITRD
	;;
	-a)
	[ "$UID" -ne 0 ] && echo "运行此项功能需要 root 权限！"
	MK_APP
	;;
	*)
	echo -e "$0 -i : 创建 initrd 文件和内核包 002-kernel.app\n$0 -a : 创建软件模块（交互模式）"
esac
